//
//	异步FIFO，位宽为16bit，depth 512
//



module FIFO(
	
	input					rst,		
	
	//读
	input					rclk, 					//读时钟
	input					r_en,					//读使能
	output reg[15:0]		r_data,					//读出的数据
	output					r_empty,				//是否为空
	
	
	//写
	input					wclk,					//写时钟
	input					w_en,					//写使能
	input[15:0]				w_data,					//写入的数据
	output					w_full,					//是否已经写满
	
	
	output reg[8:0]		    data_count					//已经有的数据		
);

reg[15:0]		memory[511:0];					//存储的容器
reg[8:0]		curr_read_ptr,next_read_ptr;						//读指针
reg[8:0]		curr_write_ptr,next_write_ptr;						//写指针





assign 	w_full  = (next_write_ptr == curr_read_ptr ) ? 1'b1 : 1'b0; 
assign  r_empty = ( next_read_ptr == curr_write_ptr || (next_read_ptr == next_write_ptr)) ? 1'b1 : 1'b0;




always@(posedge rclk or negedge rst)
begin
	if(rst == 1'b0)
		next_read_ptr <= 'd1;
	else if(r_en == 1'b1)
		if(r_empty == 1'b0)
			if(next_read_ptr == 'd511)
				next_read_ptr <= 'd0;
			else
				next_read_ptr <= next_read_ptr + 1'b1;
		else
			next_read_ptr <= next_read_ptr;
	else
		next_read_ptr <= next_read_ptr;
end

always@(posedge wclk or negedge rst)
begin
	if(rst == 1'b0)
		next_write_ptr <= 'd1;
	else if(w_en == 1'b1)
		if(w_full == 1'b0)
			if(next_write_ptr == 'd511)
				next_write_ptr <= 'd0;
			else
				next_write_ptr <= next_write_ptr + 1'b1;
		else
			next_write_ptr <= next_write_ptr;
	else
		next_write_ptr <= next_write_ptr;
end







//更新当前读地址
always@(posedge rclk or negedge rst)
begin
	if(rst == 1'b0)
		curr_read_ptr <= 'd0;
	else if(r_en == 1'b1)
		if(r_empty == 1'b0)
			curr_read_ptr <= next_read_ptr;
		else
			curr_read_ptr <= curr_read_ptr;
	else
		curr_read_ptr <= curr_read_ptr;		
end
//更新当前写地址
always@(posedge wclk or negedge rst)
begin
	if(rst == 1'b0)
		curr_write_ptr <= 'd0;
	else if(w_en == 1'b1)
		if(w_full == 1'b0)
			curr_write_ptr <= next_write_ptr;
		else
			curr_write_ptr <= curr_write_ptr;
	else
		curr_write_ptr <= curr_write_ptr;
end


//写数据
always@(negedge wclk)
begin
	if(w_en && w_full == 1'b0)
		memory[curr_write_ptr] <= w_data;
	else
		memory[curr_write_ptr] <= 16'hE000;
end

//读数据
always@(negedge rclk)
begin
	if(r_en && r_empty == 1'b0)
		r_data <= memory[curr_read_ptr];
	else
		r_data <= 16'hE000;
end



always@(posedge rclk or negedge rst)
begin
	if(rst == 1'b0)
		data_count <= 'd0;
	else if(curr_read_ptr >= curr_write_ptr && next_read_ptr != next_write_ptr)
		data_count <= 'd511 - curr_read_ptr + curr_write_ptr;
	else
		data_count <= curr_write_ptr - curr_read_ptr;
end


endmodule 